<template>
  <div class="containers bpm">
    <div ref="canvas" class="canvas"/>
    <property-panel class="property-panel" v-if="bpmnModeler" :modeler="bpmnModeler" :procDefKey="procDefKey"/>
    <el-button-group class="toolbar">
      <el-tooltip class="item" effect="dark" content="保存" placement="bottom">
        <el-button type="primary" size="mini" @click="save"><i class="fa fa-save"> 保存</i></el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="下载流程图" placement="bottom">
        <el-button type="mini" size="mini" @click="downloadSvg"><i class="el-icon-download"/></el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="下载流程文件" placement="bottom">
        <el-button type="mini" size="mini" @click="downloadBpmn"><i class="el-icon-download"/></el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="撤销" placement="bottom">
        <el-button size="mini"><i class="el-icon-refresh-left" @click="undo"/></el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="恢复" placement="bottom">
        <el-button size="mini"><i
          class="el-icon-refresh-right"
          :class="!canRedo?'default-undo':''"
          @click="redo"
        /></el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="放大" placement="bottom">
        <el-button size="mini" @click="zoom(0.05)"><i class="el-icon-zoom-in"/></el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="缩小" placement="bottom">
        <el-button size="mini" @click="zoom(-0.05)"><i class="el-icon-zoom-out"/></el-button>
      </el-tooltip>
    </el-button-group>
  </div>
</template>

<script>
  import BpmnModeler from 'bpmn-js/lib/Modeler' // bpmn-js 设计器
  import activitiModdleDescriptor from '@/components/ExtBpmn/activiti.json'
  import customTranslate from '@/components/ExtBpmn/customTranslate/customTranslate';
  import customControlsModule from '@/components/ExtBpmn/customControls';
  import BpmData from '@/components/ExtBpmn/BpmData'
  import {saveXml, getXml} from '@/api/wf/process'
  import PropertyPanel from '@/components/ExtBpmn/PropertyPanel'
  import defaultDiagram from '@/components/ExtBpmn/defaultDiagram'

  export default {
    components: {
      PropertyPanel
    },
    props: {
      id: {
        type: String,
        default: null
      },
      title: {
        type: String,
        default: null
      },
      procDefKey: {
        type: String,
        default: null
      }
    },
    data() {
      return {
        svgStr: null,
        bpmnModeler: null,
        element: null,
        bpmData: new BpmData(),
        scale: 1.0,
        canRedo: false
      }
    },
    mounted() {
      const canvas = this.$refs.canvas
      var customTranslateModule = {
        translate: ['value', customTranslate]
      }
      // 生成实例
      this.bpmnModeler = new BpmnModeler({
        container: canvas,
        // 添加翻译模块
        additionalModules: [
          customTranslateModule,
          customControlsModule
        ],
        moddleExtensions: {
          activiti: activitiModdleDescriptor
        },
      })

      getXml(this.id).then(res => {
        let xml = res.data
        xml = xml.replace(/<bpmn:process id="\w+">/, `<bpmn:process id="${this.procDefKey}">`)
        this.createNewDiagram(xml)
      })

      this.adjustPalette()
    },
    methods: {
      createNewDiagram(xml) {
        // 将字符串转换成图显示出来
        this.bpmnModeler.importXML(xml, err => {
          if (err) {
            this.bpmnModeler.importXML(defaultDiagram(this.procDefKey), (err) => {
              if (err) {
                console.log('create default diagram error', err)
              }
            })
          }
        })
      },
      // 调整左侧工具栏排版
      adjustPalette() {
        try {
          // 获取 bpmn 设计器实例
          const canvas = this.$refs.canvas
          const djsPalette = canvas.children[0].children[1].children[4]
          const djsPalStyle = {
            width: '130px',
            padding: '5px',
            background: 'white',
            left: '20px',
            borderRadius: 0
          }
          for (var key in djsPalStyle) {
            djsPalette.style[key] = djsPalStyle[key]
          }
          const palette = djsPalette.children[0]
          const allGroups = palette.children
          // 修改控件样式
          for (const allGroup of allGroups) {
            const group = allGroup
            for (var cKey in group.children) {
              const control = group.children[cKey]
              const controlStyle = {
                display: 'flex',
                justifyContent: 'flex-start',
                alignItems: 'center',
                width: '100%',
                padding: '5px'
              }
              if (
                control.className &&
                control.dataset &&
                control.className.indexOf('entry') !== -1
              ) {
                const controlProps = this.bpmData.getControl(
                  control.dataset.action
                )
                if (!controlProps.title) {
                  control.style['display'] = 'none'
                } else {
                  control.innerHTML = `<div style='font-size: 14px;font-weight:500;margin-left:15px;'>${
                    controlProps['title']
                    }</div>`
                  for (var csKey in controlStyle) {
                    control.style[csKey] = controlStyle[csKey]
                  }
                }
              }
            }
          }
        } catch (e) {
          console.log(e)
        }
      },
      downloadSvg() {
        const _this = this
        this.bpmnModeler.saveSVG(function (err, svg) {
          if (err) {
            console.error(err)
            return
          }
          const {filename, href} = _this.setEncoded('SVG', svg)
          if (href && filename) {
            const a = document.createElement('a')
            a.download = filename
            a.href = href
            a.click()
            URL.revokeObjectURL(a.href)
          }
        })
      },
      downloadBpmn() {
        const _this = this
        this.bpmnModeler.saveXML(function (err, xml) {
          if (err) {
            console.error(err)
            return
          }
          const {filename, href} = _this.setEncoded('BPMN', xml)
          if (href && filename) {
            const a = document.createElement('a')
            a.download = filename // 指定下载的文件名
            a.href = href //  URL对象
            a.click() // 模拟点击
            URL.revokeObjectURL(a.href) // 释放URL 对象
          }
        })
      },
      async save() {
        await this.bpmnModeler.saveSVG((err, svg) => {
          if (err) {
            console.error(err)
            return
          }
          this.svgStr = svg
          this.$emit('changStatus', 2);
        })

        this.bpmnModeler.saveXML((err, xml) => {
          if (err) {
            console.error(err)
            return
          }
          const params = {
            name: this.title,
            xml: xml,
            svg: this.svgStr,
            description: this.title
          }
          saveXml(this.id, params).then(res => {
            if (res.code === 200) {
              this.$notify({
                title: '保存成功！',
                type: 'success',
                duration: 2500
              })
            } else {
              this.$notify({
                title: res.msg,
                type: 'error',
                duration: 2500
              })
            }
          })
        })
      },
      setEncoded(type, data) {
        const encodedData = encodeURIComponent(data)
        if (data) {
          if (type === 'BPMN') {
            return {
              filename: 'diagram.bpmn',
              href: 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData,
              data: data
            }
          }
          if (type === 'SVG') {
            return {
              filename: 'diagram.svg',
              href: 'data:application/text/xml;charset=UTF-8,' + encodedData,
              data: data
            }
          }
        }
      },
      undo() {
        this.bpmnModeler.get('commandStack').undo()
        this.canRedo = this.bpmnModeler.get('commandStack').canRedo()
      },
      redo() {
        if (!this.canRedo) {
          return
        }
        this.bpmnModeler.get('commandStack').redo()
        this.canRedo = this.bpmnModeler.get('commandStack').canRedo()
      },
      zoom(val) {
        const newScale = !val ? 1.0 : ((this.scale + val) <= 0.2) ? 0.2 : (this.scale + val)
        this.bpmnModeler.get('canvas').zoom(newScale)
        this.scale = newScale
      }
    }
  }
</script>

<style lang='scss'>
  /*左边工具栏以及编辑节点的样式*/
  @import '~bpmn-js/dist/assets/diagram-js.css';
  @import '~bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
  @import '~bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
  @import '~bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
</style>
<style lang="scss" scoped>
  .property-panel {
    position: absolute;
    right: 0px;
    top: 0px;
    border-left: 1px solid #cccccc;
    width: 300px;
    height: 100%;
  }

  .bpm {
    margin-left: 60px;
    width: 95%;
  }
</style>
